package de.tuberlin.dima.dkey.util;

import java.util.LinkedList;
import java.util.Map.Entry;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

import de.tuberlin.dima.dkey.client.GTree;
import de.tuberlin.dima.dkey.nodes.GNode;
import de.tuberlin.dima.dkey.nodes.KeyNode;
import de.tuberlin.dima.dkey.nodes.WordNode;

/**
 * This class creates a tree from a json string pass
 */

public class JsonTreeHelper {
	
	
	public String createJson(GTree tree){
		String tmpS = createJsonRecur(new String(), tree, tree.getRootNodes().get(0), "").toString();
		tmpS = tmpS.substring(0, tmpS.length()-1);
		return "{" + tmpS +"}" ;
		
	}
	
	
	
	private String createJsonRecur(String json, GTree tree, GNode node, String indent){
	
		if(node instanceof  KeyNode){
			//Check the children
			
			LinkedList<GNode> children = tree.getChildren(node);

			//If one we can create the json right away
			if(children.size() == 0){
				System.err.println("The list returned nothing in JsonTreeHelper: " + tree.toString());
				return null;
			}
			
			if(children.get(0).getValue().equalsIgnoreCase("__ArrayItem__")){
				String json2 = new String();
				json2 = json2 + "\""+node.getValue()+"\":[";
				for(GNode child : children){
					String tmpS = createJsonRecur(json,tree,child, indent);
					tmpS = tmpS.substring(0, tmpS.length()-1);
					json2 = json2 + "{" + tmpS +"}," ;
				}
				json2 = json2.substring(0, json2.length()-1);
				json2 = json2 + "]-";
				return json2;
			}	
			
			//If one we can create the json right away
			if(children.size() == 1){
				return "\""+node.getValue()+"\":" + "\""+children.get(0).getValue()+"\",";
			}
			
			//If more than one we have to create an list
			if(children.size() > 1){
				json = json + "\""+node.getValue()+"\":{";
				for(GNode child : children){
						json = json + createJsonRecur(json,tree,child, indent)  ;
				}
				json = json.substring(0, json.length()-1);
				json = json + "}-";
				return json;
			}
			
		}else if(node instanceof  WordNode){
			String json2 = new String();
			//Check if ArrayItem then create new { PARSE }
			if(node.getValue().equalsIgnoreCase("__ArrayItem__")){
				LinkedList<GNode> childrenArray = tree.getChildren(node);
				for(GNode child : childrenArray){
					json2 = json2 + createJsonRecur(json2,tree,child, indent) ;
				}
			
				return json2;
			}
		}
		return json;
	}
	

	
	public GTree createTree(String json) throws com.google.gson.stream.MalformedJsonException{
		if(json.isEmpty()){
			return null;
		}
		
		GTree tree = new GTree();
		JsonParser parser = new JsonParser();
		createTreeRecur(tree, parser.parse(json), null, 0);
		return tree;
	}
	
	private String clean(String string){
		return string.replace("\"", "").toLowerCase() ;
	}

	private String createTreeRecur(GTree tree, JsonElement item, GNode parent, int level){
		if (item.isJsonArray()){
			for (JsonElement i : item.getAsJsonArray()){
				GNode arritem = tree.addWordNode("__arrayitem__");
				if(parent != null)
					tree.addBaseEdge(parent, arritem);
				createTreeRecur(tree, i, arritem, level);
			}
		}else if(item.isJsonNull()){

		}else if(item.isJsonObject()){
			for (Entry<String, JsonElement> i : item.getAsJsonObject().entrySet()){
				GNode n = tree.addKeyNode(clean(i.getKey()));
				if (n != null){
					if(parent != null)
						tree.addBaseEdge(parent, n);
					String v = createTreeRecur(tree ,i.getValue(), n, level +1);
					if(v != null){
						GNode vNode;
						if (v.startsWith("-multi-")){
							vNode = tree.addMultiValueNode(v.substring(v.indexOf(":")+1));
						}
						else if (v.contains(" ")){
							vNode = tree.addTextNode(clean(v));
						} else {
							vNode = tree.addWordNode(clean(v));
						}	
					
						tree.addBaseEdge(n, vNode);
							
					}
				}

			}

		}else if(item.isJsonPrimitive()){
			return clean(item.getAsString());
		}else{
			System.err.println("Don't know element: " + item);
		}

		return null;
	}
}
